home *** CD-ROM | disk | FTP | other *** search
/ Power CD / Power CD ATARI-Rechner Lieben.iso / UTILITY / MAKE / READ_ME < prev    next >
Encoding:
Text File  |  1992-08-03  |  33.4 KB  |  519 lines

  1. Kurze Erklärung zum Make-Interpreter                      Aachen, Juli 1989
  2.  
  3. Sinn und Aufgabe:
  4.   Dieses Programm sollte die Unzulänglichkeiten meiner Kopmmandoshell 
  5. lindern helfen. Es sollte in der Lage sein, vermittels weniger spezieller 
  6. Befehle den Aufruf von Compiler, Linker, Editor in logischer Abfolge zu 
  7. steuern. Dazu sind offenbar Mechanismen erforderlich, die Programmstarts 
  8. ermöglichen und die Returnwerte zur Fehlerabfrage zur Verfügung stellen. 
  9. Desweiteren benötigt man Zeitabfragefunktionen, die es erlauben, den 
  10. Compiler wirklich nur dann starten zu müssen, wenn dies erforderlich ist. 
  11. In der Regel wird ein Altersvergleich von Quell- und Objektdatei hierfür 
  12. genügen. In der vorliegenden Version stehen neben einigen einfachen 
  13. Anweisungen auch vier Strukturbefehle zur Verfügung, die recht 
  14. übersichtliche Programmierung erlauben: IF/ELSE/ENDIF, WHILE/AGAIN (mit 
  15. BREAK/CONTINUE), REPEAT/UNTIL und FOR-TO-STEP/NEXT. Alle sind bis zum 
  16. Überlaufen des Stapels schachtelbar.
  17.  
  18. Allgemeine Anweisungen und Syntaxregeln:
  19.   Die zu bearbeitende Prozedur muß als ASCII-Datei abgespeichert sein und 
  20. muß unbedingt auf ".mke" enden. Das vorliegende Programm wertet zunächst 
  21. die Kommandozeile aus, wenn hier ein Argument vorhanden ist, welches durch 
  22. ein führendes "-" gekennzeichnet ist, wird es als Name der Prozedur 
  23. benutzt. Der Interpreter hängt nur noch ein ".mke" an. Ansonsten wird die 
  24. erste Datei im aktuellen Verzeichnis, die auf ".mke" endet, als 
  25. Makeprozedur abgearbeitet. Gibt es keine solche, dann erfolgt eine 
  26. Fehlermeldung. Soll das Programm vom Desktop gestartet werden, muß es also 
  27. in make.ttp umbenannt werden, oder es muß sichergestellt werden, daß sich 
  28. maximal eine .mke Datei im aktuellen Verzeichnis befindet. Es empfiehlt 
  29. sich aber die Verwendung einer Kommandoshell. Mit den übrigen 
  30. Kommandozeilenargumenten wird wie folgt verfahren: sie werden der Reihe 
  31. nach in die vordefinierten Stringvariablen kopiert und ihre Anzahl in der 
  32. vordefinierten Variable DONE gespeichert. Sie können dann mit Hilfe der 
  33. Stringfunktionen ausgewertet werden.
  34.   Eine Zeile enthält beliebig viele Kommandos, die durch ";" getrennt 
  35. werden. Das letzte Kommando einer Zeile braucht nicht mit ";" abgeschlossen 
  36. werden. Ein Kommando kann mit beliebig vielen Spaces anfangen, um so eine 
  37. strukturorientierte Schreibweise zu ermöglichen. Danach folgt entweder ein 
  38. großgeschriebenes Schlüsselwort, oder das Kommando wird als zu startendes 
  39. Programm interpretiert. Im ersten Fall wird bei korrekter Syntax der Befehl 
  40. ausgeführt, im letzteren wird alles bis zum ersten Trennzeichen als Pfad 
  41. und Dateiname des zu startenden Programmes interpretiert, der ganze Rest 
  42. des Kommandos wird als Kommandozeile weitergereicht. Der Rückgabewert wird 
  43. in der vordefinierten Variablen RC zur Verfügung gestellt. Hieraus ergibt 
  44. es sich, daß relativ häufig die zunächst unsinnig erscheinende 
  45. Fehlermeldung "PGM-Aufruf: ... existiert nicht" erfolgt, wenn man sich 
  46. vertippt hat. Schlüsselworte müssen von den folgenden Argumenten stets 
  47. durch mindesten ein Leerzeichen getrennt sein. Jede Prozedur muß durch END. 
  48. beendet werden, alles was danach folgt wird ignoriert. Vor dem ersten 
  49. Befehl dürfen eine beliebige Anzahl von Funktionen definiert werden.
  50.  
  51. Beschreibung der einzelnen Kommandos und Funktionen:
  52. Vorbemerkungen: 
  53.   Pfadangabe sei im folgenden eine komplette Angabe von Pfad und Name einer 
  54. Datei.
  55.   Ausdruck sei eine Zeichenkette, die sich zu einem numerischen Wert 
  56. berechnen läßt (stets long int). Zugelassen als Bezeichner sind 
  57. Zeichenketten, die aus Klein- bzw. Großbuchstaben und dem Unterstrich 
  58. bestehen. Lediglich die ersten acht Zeichen sind jedoch signifikant. Noch 
  59. nicht belegte Variablen werden nach guter alter Basicmanier als Null 
  60. angenommen. Zuweisung an Variablen: siehe "LET". Folgende Operatoren stehen 
  61. zur Verfügung (in absteigender Rangfolge): ! (logisches not) ; 
  62. *,/,%(modulo) ; +,- ; <,>,==,!=,<=,>= ; &&,& (logisches und bitweises und) 
  63. ; ||,| (dito mit oder) . Die logischen Operatoren , sowie die 
  64. Vergleichsoperatoren liefern Eins für wahr und Null für unwahr. Es dürfen 
  65. verknüpft werden: Variablen, vordefinierte Funktionen, Zahlen- und 
  66. Zeichenkonstanten. Ein Beispiel für letztere: 'A' liefert den Wert 65. 
  67. Zahlenkonstanten können mit dem Symbol '$' versehen werden. Sie werden dann 
  68. als Hexadezimalzahlen ausgewertet. Die Rangfolge kann wie üblich mit 
  69. Klammern aufgehoben werden. Für die Pascal bzw. Modula-Programmierer, denen 
  70. der Umgang mit der Darstellung von Wahrheitswerten durch Integerwerte sowie 
  71. mit Bitoperatoren nicht vertraut ist, seien hier einige Beispiele für 
  72. Ausdrücke angegeben:
  73. (3*3%7==2)+(7>5)*99 (liefert 100)
  74. (3*3%7==2)+(7>5)*99 && 98=='b' (liefert 1)
  75. !!!!(4*5+3/(5+8)) (liefert 1)
  76. 7&4|$10&ff (liefert 20)
  77. !0 (liefert 1)
  78.  
  79. Einige Worte zu den Stringvariablen
  80.   Anders als bei numerischen Variablen, sind bei der Stringverarbeitung 
  81. sehr enge Grenzen gesetzt worden. Es steht ausschließlich das 16 Elemente 
  82. umfassende Array FN[...] zur Verfügung. Es gibt keine Möglichkeit auf 
  83. einzelne Zeichen zuzugreifen, die Verarbeitung beschränkt sich somit 
  84. Zuweisung, Vergleich und Addition ganzer Zeichenketten. Da die 
  85. Stringverarbeitung eigentlich nur zur Generierung und Auswertung von 
  86. Kommandozeilen vorgesehen ist, habe ich ihre Länge auf 128 Zeichen 
  87. begrenzt. Dadurch entfiel die Implementierung einer dynamischen 
  88. Speicherverwaltung mit all ihren Problemen. Ein Begrif, den ich häufiger 
  89. verwenden möchte, ist die Stringexpansion. Darunter verstehe ich folgendes: 
  90. alles weitere des betreffenden Kommandos wird Zeichen für Zeichen als 
  91. String betrachtet, lediglich wenn die Auswertung auf FN[<Ausdruck>] trifft, 
  92. wird dies durch den Inhalt der entsprechenden Variablen ersetzt. Dieses 
  93. Ersetzen kann unterdrückt werden, indem ein Hochzeichen (") eingefügt wird. 
  94. Nun wird bis zum nächsten " alles orginalgetreu übernommen. Das " selbst 
  95. kann also nicht in den String übernommen werden. Die Expansion bricht ab, 
  96. wenn sie auf ein Komma oder eine Klammer-zu trifft. Sollen diese Zeichen in 
  97. den String, dann müssen sie in Hochzeichen gesetzt werden. Die 
  98. Stringexpansion wird bei einigen stringverarbeitenden Funktionen 
  99. angewendet.
  100.  
  101. Einzelne Kommandos (nicht mit Funktionen zu verwechseln, welche nur in 
  102. Ausdrücken stehen dürfen und durch Funktionsklammern kenntlich sind): 
  103.   *** PUTS ***: Ausgabe an Stdout (vergleiche OUT_TO). Die Argumente können 
  104. in beliebiger Anzahl vorhanden sein und müssen durch Kommata getrennt 
  105. werden. Zulässige Argumente sind insbesondere in Hochzeichen 
  106. eingeschlossene Zeichenketten, oder Ausdrücke, welche dann natürlich vorher 
  107. ausgewertet werden. Vor die Ausdrücke darf ein "h:" gesetzt werden. In 
  108. diesem Fall erfolgt die Ausgabe im Hexadezimalsystem (wie für Hexzahlen 
  109. üblich als vorzeichenlose Zahl). Auch ein "d:" für Dezimalausgabe ist 
  110. zulässig, wird aber ohnehin als default angenommen. Ein "c:" bewirkt die 
  111. Ausgabe als Zeichen, z.b. kann man mit PUTS c:27, "E" den Bildschirm 
  112. löschen. Da die 27 als Zeichen ausgegeben wird, kann sie vom VT 52 Emulator 
  113. als Escape erkannt werden. Somit stehen alle Steuersequenzen zur Verfügung. 
  114. Als weiteres Argument darf FN[...] geschrieben werden. Der entsprechende 
  115. String wird ausgegeben. Ein spezielles Argument ist DATE, welches Datum und 
  116. Uhrzeit in üblicher Formatierung ausgibt. DATE ist aber keineswegs eine 
  117. vordefinierte Variable, kann also wirklich nur von PUTS erkannt werden. 
  118. Wird hinter das letzte Argument ein Punkt gesetzt, dann wird die Ausgabe 
  119. mit CR/LF abgeschlossen, ansonsten erfolgt die Ausgabe des nächsten PUTS 
  120. direkt hinter dem zuletzt ausgegebenen Zeichen.
  121.   *** SPACES ***: Ein Argument vom Typ Ausdruck. Es werden soviele 
  122. Leerzeichen ausgegeben wie der Wert des Ausdrucks modulo 80.
  123.   *** PUTC, SPACEC ***: wie die beiden vorhergehenden, jedoch erfolgt die 
  124. Ausgabe grundsätzlich auf dem Bildschirm.
  125.   *** LET ***: Hierdurch wird eine Zuweisung an eine Variable vorgenommen. 
  126. Die auf LET folgende Zeichenkette muß wie folgt aufgebaut sein: gültiger 
  127. Variablenname (s.o.), evtl. Leerzeichen, "=", evtl. Leerzeichen, 
  128. fehlerfreier Ausdruck. Die Anzahl der möglichen Variablen ist nur durch den 
  129. Speicherplatz begrenzt. Da hier aber keine Abfrage erfolgt, sollte man 
  130. nicht mehr als einige Tausend Variablen einführen, sonst gibt's einen 
  131. 2-Bomben-Bus-Error. Bereits belegte Variablen werden bei einer Zuweisung 
  132. mit dem neuen Wert überschrieben. Nicht belegte Variablen werden als Null 
  133. angenommen. Vorsicht: bei allen mir bekannten Programmiersprachen kann auf 
  134. eine Kennzeichnung einer Zuweisung verzichtet werden, daher vergißt man das 
  135. LET allzuleicht. Dies führt dann zur Fehlermeldung "Fehler in Dateiname", 
  136. da die Zuweisung als Programmaufruf interpretiert wird.
  137.   *** LONGPOKE ***: Argumente sind eine Adresse und durch Komma getrennt 
  138. ein Wert. Dieser wird in der angegebenen Adresse abgespeichert. Es wird im 
  139. Supervisormode gearbeitet, daher Vorsicht vor Abstürzen! Es muß unbedingt 
  140. vermieden werden, eine ungerade Adresse anzusprechen, um den 
  141. 3-Bomben-Adress-Error zu vermeiden. Vergleiche auch die Funktion 
  142. LONGPEEK().(s.u.). Diese Funktionen sollen die Systemvariablen zugänglich 
  143. machen.
  144.   *** DEL ***: Argument ist eine Pfadangabe. Die entsprechende Datei wird 
  145. gelöscht wenn möglich, RC erhält den Wert 1 im Erfolgsfalle, sonst 0. DEL 
  146. wertet Wildcards aus, es werden also alle auf das Muster passende Dateien 
  147. gelöscht.
  148.   *** GEM ***: Dieses Schlüsselwort am Beginn einer Zeile, die ansonsten 
  149. genau den Regeln eines Programmaufrufs genügt (siehe unten), bewirkt, daß 
  150. vor dem eigentlichen Programmstart noch der Bildschirm mit dem 
  151. Desktopraster überschrieben wird. Einige Gemprogramme, die dies leider 
  152. nicht selbst besorgen, erfordern also die Benutzung des Befehls.
  153.   *** RETURN ***: unbedingter Abbruch der Prozedur, wenn im Hauptprogramm 
  154. benutzt.
  155.   *** GOSUB, FUNC, ENDFUNC ***: siehe Funktionen.
  156.   *** CHG_EXT ***: erstes Argument ist eine Stringvariable. Ihr Inhalt wird 
  157. als Pfadangabe interpretiert. Gelingt dies nicht, gibt es eine 
  158. Fehlermeldung. Ansonsten wird die Dateierweiterung der spezifizierten Datei 
  159. gegen das zweite, durch Komma abgetrennte Argument ausgetauscht. Gab es 
  160. zuvor keine Erweiterung, so wird noch ein Punkt eingefügt. Das zweite 
  161. Argument besteht lediglich aus ein bis drei Buchstaben, nicht in 
  162. Hochzeichen eingeschlossen. Sinn dieser Anweisung ist es, abhängige Dateien 
  163. zu ermitteln. Es können z.B. mit SEARCH *.C alle Quelltextdateien gesucht 
  164. werden und mit Hilfe von CHG_EXT und DATE_OF ein Altersvergleich mit den 
  165. gleichnamigen .O Dateien vorgenommen werden.
  166.   *** SHOWC ***: Argument ist eine Pfadangabe. Die entsprechende Datei wird 
  167. unabhänig von der Ausgabeumlenkung auf dem Bildschirm ausgegeben. Typische 
  168. Anwendung dürfte die Ausgabe der Fehlerdatei nach dem Übersetzungvorgang 
  169. sein.
  170.   *** SHOWS ***: wie SHOWC, aber Ausgabe über Standardkanal, also 
  171. umlenkbar.
  172.   *** OUT_TO ***: Die umlenkbare Ausgabe wird in die als Argument 
  173. angegebene Datei gelenkt. Umlenkbar sind sowohl PUTS, wie auch SPACES und 
  174. die Ausgaben der meisten der gängigen .tos oder .ttp Programme. 
  175. Erforderlich ist die Umlenkung, weil kein Fehlerkanal im TOS besteht und 
  176. die Compiler somit gezwungen sind, alle Fehlermeldungen über den 
  177. Standardkanal auszugeben. Man lenkt die Ausgabe also vor dem Aufruf des 
  178. Compilers um, etwa in "fehler.err", und kann die Liste der Fehler nachher 
  179. im Editor verwenden. Für die Rückumlenkung auf die Konsole gibt es den 
  180. vordefinierten Dateinamen "con". Die vordefinierten Namen für Drucker und 
  181. serielle Schnittstelle lauten "printer" und "aux". Prinzipiell könnte 
  182. OUT_TO im Zusammenhang mit SHOWS zum Kopieren von Dateien verwendet werden, 
  183. jedoch erfolgt eine Aufbereitung der Zeilenendezeichen, so daß dies 
  184. grundsätzlich auf reine ASCII-Dateien beschräbnkt bleiben sollte.
  185.   *** SEARCH ***: Argument ist eine Pfadangabe, die in der Regel Wildcards 
  186. enthalten dürfte. Es werden alle Dateinamen, die auf das angegebene Muster 
  187. passen, der Reihe nach in die Stringvariablen kopiert. Dabei wird mit FN[0] 
  188. angefangen. Die gefundene Anzahl wird in DONE abgespeichert. Es darf ein 
  189. durch Komma abgetrennter Ausdruck folgen, der das Dateiattribut angibt, das 
  190. die gefundene Datei besitzen sollte
  191.   *** GETSTR ***: Argument ist eine Stringvariable. Es wird ein String von 
  192. der Tastatur eingelesen und an die Variable zugewiesen. Vorsicht: im 
  193. allgemeinen wird man wohl Dateinamen einlesen. Dies ist insofern kritisch, 
  194. als keine Möglichkeit besteht, Tippfehler zu tolerieren. Wird nämlich eine 
  195. Funktion aufgerufen, die eine Pfadangabe erwartet, erfolgt sofortiger 
  196. Abbruch der Prozedur, wenn "Fehler in Dateiname" vorliegt.
  197.   *** STRCPY ***: erstes Argument ist eine Stringvariable. Das zweite kann 
  198. ein in Hochzeichen eingeschlossener String, oder eine zweite Stringvariable 
  199. sein. Es erfolgt keine Expansion. Die Argumente werden durch Komma 
  200. getrennt. Der zweite String wird an den ersten zugewiesen.
  201.   *** STRCAT ***: Für die Argumente gilt das gleiche wie bei STRCPY. Der 
  202. zweite String wird an den ersten angehängt, das Ergebnis steht im ersten.
  203.   *** # ***: Einleitung eines Kommentars. Alles bis zum nächsten 
  204. Kommandotrennzeichen wird überlesen. Auch auf dieses Kommando muß zunächst 
  205. ein Leerzeichen folgen.
  206.   *** WHILE, AGAIN ***: abweisende Schleife. Ist der Ausdruck hinter dem 
  207. WHILE von Null verschieden, dann werden die Befehle zwischen WHILE und 
  208. AGAIN solange ausgeführt, bis sich dies geändert hat. Ansonsten wird hinter 
  209. dem korrespondierenden AGAIN fortgefahren. Wird in der Schleife ein BREAK 
  210. gefunden, dann wird die Schleife unmittelbar an dieser Stelle verlassen und 
  211. hinter dem korrespondierenden AGAIN fortgefahren. Bei CONTINUE wird sofort 
  212. mit der nächsten Überprüfung der WHILE-Bedingung fortgefahren. Diese beiden 
  213. Befehle werden nur von der WHILE-Schleife erkannt, man darf sie also nie in 
  214. den anderen benutzen, auch dann nicht, wenn diese von einer WHILE-Schleife 
  215. umschlossen werden. Dahingegen dürfen die Befehle in einer beliebig 
  216. geschachtelten Anzahl von IFs benutzt werden, es wird dann die 
  217. nächstumschließende WHILE-Schleife angesprochen.
  218.   *** REPEAT, UNTIL ***: nicht abweisende Schleife, UNTIL hat einen 
  219. Ausdruck als Argument. Die Kommandos zwischen REPEAT und UNTIL werden 
  220. ausgeführt bis der Ausdruck wahr (also ungleich Null) wird, aber mindestens 
  221. einmal.
  222.   *** IF, ELSE, ENDIF ***: IF hat ein Argument, einen Ausdruck. Ist dieser 
  223. ungleich Null, also wahr, dann werden die Anweisungen zwischen IF und ELSE 
  224. ausgeführt, sonst diejenigen zwischen ELSE und ENDIF. ELSE darf weggelassen 
  225. werden. Vorsicht bei IF, ELSE IF, ... , ELSE IF, ENDIF Konstruktionen: da 
  226. ein ELSE und das folgende IF gewöhnlich in derselben Zeile stehen, müssen 
  227. sie durch Semikolon getrennt werden. Auch müssen in der letzten Zeile der 
  228. Konstruktion soviele ENDIFs stehen (auch durch ; getrennt), wie IFs 
  229. verwendet wurden!
  230.   *** FOR, TO, STEP, NEXT ***: abweisende Schleife. Zwischen FOR und TO muß 
  231. eine Zuweisung erfolgen, hier jedoch ohne das Schlüsselwort LET. Nach dem 
  232. FOR steht ein Ausdruck. Folgt nun das optionale STEP, dann muß danach als 
  233. letztes Element des Kommandos noch ein Ausdruck folgen. Fehlt STEP, wird 
  234. als Schrittweite Eins genommen, sonst das Ergebnis des Ausdrucks. Die 
  235. Schleife wird solange ausgeführt, bis die Variable, die in der Zuweisung 
  236. verwendet wurde, echt größer ist als der Ausdruck hinter TO. 
  237. (Schrittweite>0 vorausgesetzt, ansonsten analog) Sehr wichtig: Die 
  238. Auswertung der Ausdrücke erfolgt nur vor dem Eintritt in die Schleife, 
  239. daher kann sich die Schrittweite über einen Laufzeitausdruck nicht 
  240. verändern! Mit NEXT wird die Schleife abgeschlossen.
  241.  
  242. Vordefinierte Funktionen:
  243. Diese Funktionen liefern numerische Werte und können somit (nur!) in 
  244. Ausdrücken verwendet werden.
  245.   *** TIME_F() ***: liefert die Systemzeit in 1/200s - Schritten ("fast"). 
  246. Nach dem ersten Aufruf erhält man einen zufälligen Wert, danach immer den 
  247. Wert, der der seit dem letzten Aufruf vergangenen Zeit entspricht. Soll ein 
  248. Programmlauf gestoppt werden, muß also vorher TIME_F() einmal mit GOSUB 
  249. aufgerufen oder einer Dummy-Variablen zugewiesen werden.
  250.   *** TIME_S() ***: liefert die Systemzeit in Sekunden ("slow"). Hierbei 
  251. ist garantiert, daß es sich um die absolute Sytemzeit handelt, d.h. durch 
  252. Divisionen und Subtraktionen läßt sich die Uhrzeit gewinnen. Die beiden 
  253. Funktionen können zum Stoppen von Programmlaufzeiten benutzt werden.
  254.   *** DATE_OF(Pfadangabe) ***: liefert das Datum der Dateierstellung der 
  255. als Argument übergebenen Datei. Existiert sie gar nicht, so wird Null 
  256. zurückgegeben. Dies entspricht dem höchstmöglichen Alter, das eine Datei 
  257. haben kann. Mit dieser Funktion kann man die Abhängigkeiten von Quelltexten 
  258. von einander untersuchen und überflüssige Compileraufrufe vermeiden. Das 
  259. Argument zwischen den Klammern wird zuvor expandiert, es können also 
  260. Stringvariablen verwendet werden.
  261.   *** GETCHAR() ***: wartet auf eine Tastatureingabe und liefert den 
  262. ASCII-Kode der Taste. Es wird kein Echo ausgegeben, dies muß gegebenenfalls 
  263. durch PUTS erfolgen.
  264.   *** SCANCHAR() ***: Fragt den Tastaurpuffer ab. Liefert Null, wenn keine 
  265. Taste gedrückt wurde und wartet nicht auf eine Eingabe. Ansonsten wie 
  266. GETCHAR().
  267.   *** LONGPEEK(Ausdruck) ***: Der Ausdruck wird als Adresse interpretiert 
  268. ab der ein Langwort gelesen wird. Dieses ist der Rückgabewert der Funktion. 
  269. Vergleiche Bemerkungen zu LONGPOKE.
  270.   *** STRCMP ***: erstes Argument ist eine Stringvariable, das zweite durch 
  271. Komma getrennt, ein String oder eine zweite Stringvariable. Im ersten Falle 
  272. muß dieser in Hochzeichen eingeschlossen sein, es erfolgt keine Expansion. 
  273. Die beiden Strings werden verglichen. Ergebnis ist die Differenz der 
  274. ASCII-Werte des ersten Zeichens, in dem sie sich unterscheiden. Gleichheit 
  275. von Strings muß also durch !STRCMP(...) untersucht werden.
  276.   *** GETINT ***: Es wird ein numerischer Wert eingelesen. Dieser darf als 
  277. beliebiger Ausdruck eingegeben werden, der Ausdruck wird nach den bekannten 
  278. Regeln ausgewertet und liefert den Rückgabewert der Funktion. Der Ausdruck 
  279. darf übrigens durchaus wieder die Funktion GETINT enthalten.
  280.  
  281. Selbstdefinierte Funktionen
  282.   Vor dem eigentlichen Programm dürfen Funktionen definiert werden. Eine 
  283. Funktionsdefinition beginnt durch das Schlüsselwort FUNC gefolgt vom Namen 
  284. der Funktion und symbolischen Funktionsklammern. Für die Funktionsnamen 
  285. gilt das gleiche wie für Variablennamen. Die Funktionsdefinition endet mit 
  286. dem Schlüsselwort ENDFUNC. Alle Anweisungen zwischen FUNC und ENDFUNC 
  287. werden später bei Funktionsaufrufen ausgeführt. Die Anzahl der Funktionen 
  288. ist nur durch den Speicherplatz begrenzt. Der Aufruf kann auf zwei Arten 
  289. erfolgen: durch "GOSUB Fktname()" wird die Funktion direkt aufgerufen, ihr 
  290. Rückgabewert geht verloren. Wenn die selbstdefinierte Funktion hingegen als 
  291. Teil eines Ausdrucks benutzt wird, kann ihr Rückgabewert verarbeitet oder 
  292. an eine Variable zugewiesen werden. In den Funktionsklammern kann ein 
  293. Ausdruck als Parameter übergeben werden. Dieser steht innerhalb der 
  294. Funktion als Variable mit dem Namen der Funktion zur Verfügung. Dieser 
  295. Variablen kann in der Funktion ein neuer Wert zugewiesen werden. Dies ist 
  296. dann der Rückgabewert der Funktion, der im Ausdruck weiterverarbeitet wird. 
  297. Durch diesen Mechanismus wird eine Rekursion unterbunden, die im Prinzip 
  298. möglich wäre, jedoch äußerst sinnlos, da keine lokalen 
  299. Speichermöglichkeiten bestehen.
  300.  
  301. Programmaufruf:
  302.   Nun endlich zur eigentlichen Aufgabe des Programms. Wird die führende 
  303. Buchstabensequenz eines Kommandos nicht als Schlüsselwort erkannt, dann 
  304. wird versucht, sie als Pfadangabe zu identifizieren. Gelingt dies nicht, 
  305. dann gibt es eine Fehlermeldung, ansonsten wird die entsprechende Datei 
  306. gestartet. Der gesamte Rest des Kommandos wird expandiert und dem Programm 
  307. als Kommandozeile mit auf den Weg gegeben. Nach dem Programmstart wird der 
  308. vordefinierten Variablen "RC" der Returnwert des Programmes zugewiesen. Gab 
  309. es einen Fehler (z.B. -33 für File not found), dann erhält "RC" diesen 
  310. Fehlerwert.
  311.  
  312. Sonstiges:
  313.   Auf einen besonders tückischen Fehler möchte ich hier noch extra 
  314. hinweisen: Da Kommandozeilen nicht länger als 128 Bytes werden dürfen, kann 
  315. es hier zu Fehlermeldungen bei rein syntaktisch völlig korrekten Kommandos 
  316. kommen. Gerade beim Aufruf des Linkers hat man die 128 Byte schnell voll.
  317.   Auf der Diskette befinden sich einige Demos für Makeprozeduren, die zum 
  318. größten Teil nur als Anwendungsbeispiele der Befehle dienen sollen. 
  319. Lediglich make.mke ist ein echtes Make. Hiermit habe ich in der letzten 
  320. Phase der Programmentwicklung schon zufriedenstellend am vorliegenden 
  321. Programm arbeiten können.
  322.  
  323. ***** Erweiterungen der Version 2.0 *****              Aachen, im Mai 1992 
  324.  
  325. Nach längerer Zeit sind nun einige sinnvolle Erweiterungen vorgenommen 
  326. worden, die teilweise erkannte Mißstände beheben, zum Teil auch einfach 
  327. neue Funktionen zur Verfügung stellen. Die Kompatibilität zur ersten 
  328. Version konnte nicht gewahrt werden, jedoch ist die Ähnlichkeit der 
  329. Prozeduren groß.
  330.   Vorweg eine nützliche Kleinigkeit: Prozeduren können nun durch 
  331. gleichzeitige Betätigung von Control, Alternate und Shift-links 
  332. unterbrochen werden, allerdings wird diese Kombination nur nach jedem 
  333. zehnten Befehl abgefragt.
  334.   Auffälligste Änderung: Es können nun auch Kleinbuchstaben bei den 
  335. Schlüsselworten verwendet werden. Nach wie vor müssen diese von einem 
  336. Leerzeichen gefolgt werden, um erkannt zu werden. Es ist verführerisch, nun 
  337. in C-Syntax "if(a<B) ... " zu schreiben, dies wird aber nicht erkannt. 
  338. Groß/Kleinschreibung wird bei Bezeichnern aber nach wie vor unterschieden, 
  339. daher muß man auch noch immer RC schreiben. DONE existiert nicht mehr.
  340.   Wichtigste Änderung: Es wird jetzt der Shell-Pointer-Mechanismus genutzt. 
  341. Wenn MAKE von einer Kommandoshell gestartet worden ist, dann kann diese aus 
  342. einer Prozedur aufgerufen werden. Wenn beim Programmaufruf die Datei nicht 
  343. gefunden wird, dann wird die ganze Zeile an die Shell übergeben, wenn eine 
  344. solche vorhanden ist. Es steht somit der ganze Befehlsumfang der Shell zur 
  345. Verfügung. Expliziter Aufruf der Shell mit einem Befehl ist auch mit Hilfe 
  346. der Funktion system() möglich (s.u.). In diesem Fall wird der Returncode 
  347. der Shell als Funktionswert, in jenem über RC bekanntgemacht. Wird, wie 
  348. üblich, der Programmaufruf-Mechanismus verwendet, dann muß das 
  349. Shellkommando allerdings syntaktisch den Regeln für Dateinamen entsprechen. 
  350. Ein kleiner Nachteil ergibt sich: syntaktisch falsch geschriebene Kommandos 
  351. werden an die Shell weitergereicht, von dieser untersucht und i.a. nicht 
  352. erkannt. Die entsprechende Fehlermeldung wird jetzt natürlich nicht von der 
  353. Prozedur explizit abgefragt, und damit wäre die fehlerhafte Zeile einfach 
  354. überlesen worden. Um dies zu vermeiden, führen Shell-Fehlermeldungen stets 
  355. zu einer Warnung.
  356.   Praktischste Änderung: Nun wurden richtige Stringvariablen eingeführt. 
  357. Ihre Länge ist nach wie vor begrenzt, da sie ja zur Erzeugung von 
  358. Kommandozeilen und Programmnamen dienen sollen. Das Stringfeld FN[] ist nun 
  359. hinfällig geworden. Stringvariablen sind durch ein $ hinter dem Namen zu 
  360. kennzeichnen. Sie können, wie nunmehr alle Variablen, durch eine 
  361. Indizierung der Form '['<Ausdruck>']' modifiziert werden. Allerdings 
  362. verkürzt sich die signifikante Länge der Namen bei Feldern auf fünf 
  363. Zeichen. Der Indexbereich geht von etwa -1600 bis +1600. Der Typ einer 
  364. Variablen wird durch die jeweils letzte Zuweisung festgelegt, es existieren 
  365. also nicht zugleich 'var' und 'var$', hingegen sind gewöhnliche und 
  366. indizierte Variablen des gleichen Namens nebeneinander möglich.  Bei 
  367. Typfehlern wird die Prozedur abgebrochen. Nicht zugewiesene Variablen sind 
  368. Null (numerisch) oder leer (String). Werden Stringvariablen in numerischen 
  369. Ausdrücken verwendet, dann werden sie ausgewertet, als wenn ihr Inhalt Teil 
  370. der Prozedur wäre, jedoch bilden sie dabei eine vollständig geschlossene 
  371. Klammerebene. 'Syntaxfehler im Ausdruck' ist nun höchstwahrscheinlich auf 
  372. einen nicht arithmetisch interpretierbaren Stringinhalt zurückzuführen! Die 
  373. Kommandozeilenargumente liegen jetzt im Feld argv$[1..argc], nach 
  374. Prozedurstart gibt argc also die Anzahl der Kommandos an. Dazu kommt noch 
  375. der Name der Prozedur in der Variable argv$[0].
  376.   Bei der Stringexpansion hat sich durch die neuen Variablen einiges 
  377. geändert. ""-Zeichen schließen einen Teil ein, der unverändert übernommen 
  378. wird, ''-Zeichen dürfen den gesamten zu expandierenden Bereich umfassen, um 
  379. definierte Enden festzulegen. Insbesondere am Zeilenende verbergen sich oft 
  380. ungewollte Leerzeichen, die normalerweise mit in den String übernommen 
  381. würden, andererseits werden ohne Hochzeichen führende Leerzeichen 
  382. ausgelassen; beidem kann man hiermit entgegenwirken. ' a$ ' ergibt einen 
  383. String, der vor und nach dem Inhalt von a$ genau ein Leerzeichen 
  384. beinhaltet. Ist das erste Zeichen kein ', dann haben weitere ' keine 
  385. spezielle Bedeutung, ansonsten bricht die Expansion beim nächsten ' ab. 
  386. Folgen dann noch weitere Zeichen in der Zeile, gibt es einen Syntaxfehler. 
  387. /,",' kann man durch //, /", /' in den expandierten String einfügen, in 
  388. konstanten Strings (durch "" erzeugt) ist davon nur /" wirksam. / dient 
  389. auch als Trennsymbol: soll vor einem Variableninhalt ohne Leerzeichen ein 
  390. Buchstabe stehen, dann geht es nicht ohne weiteres: 'halloa$' würde nicht 
  391. als "hallo"a$ interpretiert werden, sondern es würde nach einer 
  392. Stringvariable des Namens halloa gesucht werden. So muß man schreiben: 
  393. 'hallo/a$'. (Auch "hallo"a$ ist nicht ganz zufriedenstellend, weil hallo 
  394. dann nicht als numerische Variable erkannt werden kann.) Alle 
  395. Nichtbuchstaben sind gleichfalls Trennzeichen. Numerische Variablen werden 
  396. durch ihren Inhalt als vorzeichenbehaftete Zahl ersetzt, Ausdrücke werden 
  397. nicht ausgewertet. Man sollte wegen der vielfältigen 
  398. Expansionsmöglichkeiten tunlichst auf "" zurückgreifen, um ungewollte 
  399. Effekte zu vermeiden. Man hat ja leicht ein paar kurze Variablennamen wie 
  400. a, i, t etc., die expandiert würden, sofern sie von Trennzeichen umgeben 
  401. sind. An Variablen, die expandiert werden sollen, muß in der Vergangenheit 
  402. bereits etwas zugewiesen worden sein, hier gilt natürlich nicht das zuvor 
  403. Gesagte über Apriori-Inhalte von Variablen. Werden zu expandierende 
  404. Stringvariablen in geschweifte Klammern eingeschlossen, werden sie selbst 
  405. wieder über die gleiche Expansionsfunktion ausgewertet, jedoch mit kleinen 
  406. Unterschieden. '' hat nun keine besondere Bedeutung, es werden alle Zeichen 
  407. des Stringinhaltes übernommen. Auch wird die Expansion garantiert erst am 
  408. Inhaltsende abgebrochen, sonst wird je nach Kontext z.B. bei einem Komma 
  409. oder bei ')' (Endekennung eines Funktionsparameters) o.ä. abgebrochen. 
  410. Generell werden keine Variablennamen erkannt, die nur zur Hälfte in einem 
  411. Stringinhalt stehen und zur anderen in der Prozedurzeile. Zyklische 
  412. Verschachtelungen sind sowohl bei der Ausdrucksauswertung als auch bei der 
  413. Stringexpansion verboten und führen zur Fehlermeldung. Gewöhnlich wird 
  414. jedoch einfach der Inhalt der Stringvariablen unverändert in den 
  415. Ergebnisstring eingefügt. Die Klammer selbst kann durch {{ in den 
  416. Ergebnisstring eingefügt werden.
  417.   Im Gegensatz zu früher werden nun die Stringparameter aller Funktionen 
  418. über die Expansion gewonnen, solange es sich nicht um "lvalues" handelt, 
  419. also um Angaben von Variablen, an die dann zugewiesen werden soll.
  420.   Eine schreibgeschützte Variable version (oder VERSION) liefert die 
  421. Versionsnummer des Interpreters als dreistellige Zahl.
  422.  
  423. Geänderte Kommandos:
  424.   *** PUTS, PUTC ***: Hier wird die Stringexpansion nach wie vor nicht 
  425. angewandt, da auch Ausdrücke ausgewertet werden sollen. Als weiteres 
  426. mögliches Argument kommen nun die Stringvariablen hinzu, aber eben jeweils 
  427. nur einzeln. Das schon früher funktionierende d: vor einem Ausdruck ist nun 
  428. nicht mehr bedeutungslos: vor eine Stringvariable gesetzt bewirkt es, daß 
  429. diese als dezimal anzuzeigender Ausdruck ausgewertet wird. Fängt ein 
  430. Ausdruck mit einer Stringvariablen an, dann ist es jetzt sogar notwendig, 
  431. ein d: davorzusetzen, da sonst nach Ausgabe der Variablen eine 
  432. Fehlermeldung erfolgte. Desweiteren hat sich DATE in DATE$ verwandelt.
  433.   *** SEARCH ***: es können nun mehrere Pfade angegeben werden, wobei 
  434. Stringexpansion erfolgt. Jedem Pfad kann ein optionales Suchattribut 
  435. zugeordnet werden, das ihm nun jedoch in runden Klammern folgen muß, das 
  436. Komma dient jetzt der Trennung der verschiedenen Pfade. Auch muß nun 
  437. mitgeteilt werden, wo das Ergebnis abgespeichert werden soll. Dazu wird der 
  438. neu eingeführte erste Parameter verwendet. Er muß syntaktisch eine nicht 
  439. indizierte Stringvariable darstellen. Anschließend wird das zugehörige Feld 
  440. die gefundenen Dateinamen im Indexbereich 1...max enthalten. Der Wert von 
  441. max wird in der numerischen Variable desselben Namens abgelegt. 
  442. (gewöhnliche und Feldvariablen desselben Namens können gleichzeitig 
  443. existieren)
  444.   *** OUT_TO ***: Statt 'printer' und 'con' können nun auch die Bezeichner 
  445. 'prn' und 'stdout' als gleichwertige Angaben benutzt werden.
  446.   *** GETSTR ***: Es können nun auch Leerzeichen eingegeben werden. 
  447. Einziger Operand ist eine Stringvariable. Existierte eine numerische 
  448. Variable des Namens, dann erfährt sie jetzt eine Typumwandlung.
  449.   *** LET ***: Es können nun auch Zuweisungen an Stringvariablen 
  450. vorgenommen werden, die die lästige Verwendung von STRCPY und STRCAT 
  451. überflüssig machen. Dabei wird STRCPY durch '=', STRCAT durch '+=' 
  452. ausgeführt. Die rechte Seite der Zuweisung wird durch Stringexpansion 
  453. gewonnen. Bei += wird die Variable der linken Seite auf "" gesetzt, wenn 
  454. sie vorher als numerische Variable oder gar nicht existierte. Bei = bleibt 
  455. die Variable der linken Seite zur Zeit der Berechnung der rechten Seite 
  456. erhalten, auch wenn es vorher eine numerische Variable war.
  457.   *** STRCAT, STRCPY ***: Existieren nicht mehr.
  458.   *** LONGPOKE ***: Existiert nicht mehr, wurde in poke umgewandelt.
  459.  
  460. neue Kommandos:
  461.   *** warn_ver ***: als Argument folgt ein Ausdruck, der eine 
  462. Make-Versionsnummer (dreistellig, mal hundert) angibt. Ist diese höher, als 
  463. die des verwendeten Interpreters, dann wird die Prozedur mit einem 
  464. entsprechenden Hinweis abbgebrochen.
  465.   *** warn_sys ***: die Prozedur wird mit einem entsprechenden Hinweis 
  466. abgebrochen, wenn keine Kommandoshell installiert ist.
  467.   *** exit ***: Argument ist numerisch. Ist der Wert gleich Null, dann 
  468. passiert nichts. Bei Werten ungleich Null wird die Prozedur unbedingt 
  469. beendet. Ist der Wert größer Null, dann wird Null zurückgegeben, sonst der 
  470. Wert selbst.
  471.   *** dir ***: es folgt die Angabe einer Stringvariablen, ein Komma und 
  472. eine Pfadangabe. Dann wird eine Dateiauswahlbox angezeigt, die wie üblich 
  473. bedient wird. Der Stringvariablen wird der Name der ausgewählten Datei 
  474. zugewiesen. Bei Wahl von 'Abbruch' wird ihr Inhalt nicht geändert. An RC 
  475. wird die boolsche Aussage zugewiesen, ob eine Auswahl erfolgte.
  476.   *** poke ***: wie das frühere LONGPOKE, jedoch mit drittem, numerischen, 
  477. durch Komma abgetrenntem Argument, das angibt, ob Byte-, Wort- oder 
  478. Langwortzugriff erfolgen soll. Es erfolgt eine Wortgrenzenprüfung, jedoch 
  479. ist trotzdem höchste Vorsicht geboten, da im Supervisormodus gearbeitet 
  480. wird. Bytes werden vorzeichenlos behandelt, Wort und Langwort sind 
  481. vorzeichenbehaftet. Das dritte Argument wird so ausgewertet, daß man 
  482. Zeichenkonstanten übergeben kann, also z.B. 'b' oder 'B' für Byte-Zugriff. 
  483. Vergleiche peek().
  484.  
  485. geänderte Funktionen:
  486.   *** LONGPEEK() ***: Existiert nicht mehr, wurde durch peek() ersetzt.
  487.  
  488. neue Funktionen:
  489.   *** istomake() ***: Erstes Argument: es wird festgestellt, ob diese Datei 
  490. wirklich jünger ist, als alle weiteren angegebenen. Dann liefert die 
  491. Funktion false, sonst zeigt sie an, daß z.B. compiliert werden muß. Es 
  492. folgt ein Doppelpunkt und mindestens ein weiteres Argument. Weitere 
  493. Abhängigkeiten können durch Kommas getrennt angegeben werden. Alle 
  494. Argumente werden über Stringexpansion gewonnen und müssen als fehlerfreie 
  495. Pfadangaben interpretierbar sein.
  496.   *** exists() ***: Ein durch Expansion gewonnenes Argument, das als 
  497. Pfadangabe interpretiert wird. Die Funktion liefert die boolsche Aussage, 
  498. ob die entprechende Datei existiert.
  499.   *** system() ***: Ein durch Expansion gewonnenes Argument, das im ganzen 
  500. als Kommando an die Shell übergeben wird, wenn eine solche vorhanden ist, 
  501. sonst wird die Prozedur abgebrochen. Funktionswert ist der Returncode der 
  502. Shell. Eine Warnung bei Fehlermeldungen der Shell unterbleibt hier aus 
  503. einsichtigen Gründen. Wird kein Argument übergeben, d.h. system() 
  504. geschrieben, dann liefert die Funktion eine Aussage über das Vorhandensein 
  505. einer Shell.
  506.   *** toupper(), tolower() ***: Ein numerisches Argument, dessen Groß-, 
  507. bzw. Kleinschreibung seiner Interpretation als Zeichen zurückgegeben wird, 
  508. wenn diese existiert. Sonst wird das Argument unverändert zurückgegeben.
  509.   *** extcmp() ***: Zwei Stringargumente, deren erstes einen Pfad angibt. 
  510. Das zweite darf maximal drei zusammenhängende Zeichen (ohne '.') 
  511. beinhalten. Ohne auf Groß-/Kleinschreibung zu achten, wird wie bei STRCMP 
  512. der String mit der Erweiterung des Dateinamens des Pfades verglichen.
  513.   *** strcmpnc() ***: Arbeitet genau wie STRCMP() jedoch wird nicht auf 
  514. Groß-/Kleinschreibung geachtet.
  515.   *** peek() ***: hat nun zwei numerische, durch Komma getrennte Argumente, 
  516. wobei das letzte angibt, welche Wortbreite gelesen werden soll. Das erste 
  517. ist unverändert die Adresse, an der gelesen wird. Es gelten alle 
  518. Bemerkungen, die zu poke gemacht wurden.
  519.